/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package io.netty.example.echo;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.util.concurrent.FastThreadLocal;
import io.netty.util.concurrent.FastThreadLocalThread;
import io.netty.util.internal.InternalThreadLocalMap;

/**
 * Echoes back any received data from a client.
 */
// https://www.jianshu.com/p/3943c78a9634 transport 这块的一个详细流程说明
// https://elijahte.gitee.io/categories/Netty/ 相关文章
/*
各个组件的介绍
https://blog.csdn.net/weixin_54232666/article/details/131533917#:~:text=%E4%B8%80%E3%80%81%20netty%20%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B%201%20channel%E5%8F%AF%E4%BB%A5%E7%90%86%E8%A7%A3%E4%B8%BA%E6%95%B0%E6%8D%AE%E7%9A%84%E9%80%9A%E9%81%93%202%20msg%E5%8F%AF%E4%BB%A5%E7%90%86%E8%A7%A3%E4%B8%BA%E6%B5%81%E5%8A%A8%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E6%9C%80%E5%BC%80%E5%A7%8B%E8%BE%93%E5%85%A5%E6%98%AFbyteBuf%EF%BC%8C%E7%BB%8F%E8%BF%87pipeline%E7%9A%84%E5%8A%A0%E5%B7%A5%EF%BC%8C%E4%BC%9A%E5%8F%98%E6%88%90%E5%85%B6%E4%BB%96%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%AF%B9%E8%B1%A1%EF%BC%8C%E6%9C%80%E5%90%8E%E8%BE%93%E5%87%BA%E5%8F%88%E5%8F%98%E6%88%90ByteBuf,3%20%E6%8A%8Ahandler%E7%90%86%E8%A7%A3%E4%B8%BA%E6%95%B0%E6%8D%AE%E7%9A%84%E5%A4%84%E7%90%86%E5%B7%A5%E5%BA%8F%EF%BC%9A%E5%B7%A5%E5%BA%8F%E6%9C%89%E5%A4%9A%E9%81%93%EF%BC%8C%E5%90%88%E5%9C%A8%E4%B8%80%E8%B5%B7%E5%B0%B1%E6%98%AFpipeline%EF%BC%8Cpipeline%E8%B4%9F%E8%B4%A3%E5%8F%91%E5%B8%83%E4%BA%8B%E4%BB%B6%EF%BC%88%E8%AF%BB%E3%80%81%E8%AF%BB%E5%8F%96%E5%AE%8C%E6%88%90..%EF%BC%89%E4%BC%A0%E6%92%AD%E7%BB%99%E6%AF%8F%E4%B8%AAhandler%EF%BC%8C%20%E6%AF%8F%E4%B8%AAhandler%E5%AF%B9%E8%87%AA%E5%B7%B1%E6%84%9F%E5%85%B4%E8%B6%A3%E7%9A%84%E4%BA%8B%E6%83%85%E8%BF%9B%E8%A1%8C%E5%A4%84%E7%90%86%20%EF%BC%88%E9%87%8D%E5%86%99%E4%BA%86%E7%9B%B8%E5%BA%94%E4%BA%8B%E4%BB%B6%E5%A4%84%E7%90%86%E6%96%B9%E6%B3%95%EF%BC%89%EF%BC%9Bhandler%E5%88%86inbound%E5%92%8Coutbound%E4%B8%A4%E7%B1%BB%EF%BC%8C%E8%BE%93%E5%85%A5%E4%B8%BA%E5%85%A5%E6%A0%88%E5%A4%84%E7%90%86%E5%99%A8%EF%BC%8C%E8%BE%93%E5%87%BA%E4%B8%BA%E5%87%BA%E6%A0%88%E5%A4%84%E7%90%86%E5%99%A8%204%20eventLoop%E7%90%86%E8%A7%A3%E4%B8%BA%E5%A4%84%E7%90%86%E6%95%B0%E6%8D%AE%E7%9A%84%E5%B7%A5%E4%BA%BA%20%E4%B8%80%E4%B8%AA%E5%B7%A5%E4%BA%BA%E6%98%AF%E5%8F%AF%E4%BB%A5%E7%AE%A1%E7%90%86%E5%A4%9A%E4%B8%AAchannel%E7%9A%84io%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%B8%80%E6%97%A6%E5%B7%A5%E4%BA%BA%E8%B4%9F%E8%B4%A3%E4%BA%86%E6%9F%90%E4%B8%AAchannel%EF%BC%8C%E5%B0%B1%E8%A6%81%E8%B4%9F%E8%B4%A3%E5%88%B0%E5%BA%95%EF%BC%88%E7%BB%91%E5%AE%9A%EF%BC%89%20
*/
// https://zhuanlan.zhihu.com/p/606886182 常见问题
public final class EchoServer {

  static final boolean SSL = System.getProperty("ssl") != null;
  static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));

  public static void main(String[] args) {
    FastThreadLocalThread f1 = new FastThreadLocalThread(new Runnable() {
      @Override
      public void run() {
        new FastThreadLocal<Integer>().set(1);
      }
    });
    FastThreadLocalThread f2 = new FastThreadLocalThread(new Runnable() {
      @Override
      public void run() {
        new FastThreadLocal<Integer>().set(2);
      }
    });
//    new FastThreadLocalThread(new Runnable() {
//      @Override
//      public void run() {
//        FastThreadLocal f1 = new FastThreadLocal<Integer>();
//        f1.set(3);
//        FastThreadLocal f2 = new FastThreadLocal<Integer>();
//        f2.set(4);
//      }
//    }).start();
    f1.start();
    f2.start();
//    System.out.println("----, " + InternalThreadLocalMap.nextVariableIndex());
  }

  public static void main2(String[] args) throws Exception {
    // Configure SSL.
    final SslContext sslCtx;
    if (SSL) {
      SelfSignedCertificate ssc = new SelfSignedCertificate();
      sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
    } else {
      sslCtx = null;
    }

    // https://www.jianshu.com/p/bd0c76040913
    // Configure the server.
    EventLoopGroup bossGroup = new NioEventLoopGroup(2);
    EventLoopGroup workerGroup = new NioEventLoopGroup(3);
    try {
      ServerBootstrap b = new ServerBootstrap();
      b.group(bossGroup, workerGroup)
          .channel(NioServerSocketChannel.class)
          .option(ChannelOption.SO_BACKLOG, 100)
          .handler(new LoggingHandler(LogLevel.INFO))
          .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
              ChannelPipeline p = ch.pipeline();
              if (sslCtx != null) {
                p.addLast(sslCtx.newHandler(ch.alloc()));
              }
              //p.addLast(new LoggingHandler(LogLevel.INFO));
              p.addLast(new EchoServerHandler());
            }
          });

      // Start the server.
      // NioEventLoop.run 处理
      // https://zhuanlan.zhihu.com/p/362362169 流程说明
      // SingleThreadEventExecutor.execute
      ChannelFuture f = b.bind(PORT).sync();

      // Wait until the server socket is closed.
      f.channel().closeFuture().sync();
    } finally {
      // Shut down all event loops to terminate all threads.
      bossGroup.shutdownGracefully();
      workerGroup.shutdownGracefully();
    }
  }
}
